From f48b3cce024b04df08ef5fa3d8360688e1f910b7 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 21 Aug 2014 19:41:48 +0200 Subject: [PATCH] wayland: Replace clipboard implementation The wayland specific clipboard functions have been replaced by something more similar to the hooking the win32 backend does, which allows for just using the default GtkClipboard code in GTK+. As a consequence, the wayland-specific GtkClipboard implementation is now gone. https://bugzilla.gnome.org/show_bug.cgi?id=697855 --- gdk/wayland/gdkdevice-wayland.c | 375 +---------------------------- gdk/wayland/gdkselection-wayland.c | 38 +++ gdk/wayland/gdkwaylandselection.h | 36 +-- gtk/Makefile.am | 2 - gtk/gtkclipboard-wayland.c | 365 ---------------------------- gtk/gtkclipboard-waylandprivate.h | 60 ----- gtk/gtkclipboard.c | 10 +- gtk/gtkselection.c | 27 +++ 8 files changed, 77 insertions(+), 836 deletions(-) delete mode 100644 gtk/gtkclipboard-wayland.c delete mode 100644 gtk/gtkclipboard-waylandprivate.h diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 36980b3d9e..dd64f2fcd2 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -35,10 +35,6 @@ #include #include -typedef struct _DataOffer DataOffer; - -typedef struct _GdkWaylandSelectionOffer GdkWaylandSelectionOffer; - typedef struct _GdkWaylandTouchData GdkWaylandTouchData; struct _GdkWaylandTouchData @@ -93,10 +89,6 @@ struct _GdkWaylandDeviceData guint cursor_timeout_id; guint cursor_image_index; - DataOffer *drag_offer; - DataOffer *selection_offer; - - GdkWaylandSelectionOffer *selection_offer_out; struct wl_surface *pointer_surface; }; @@ -512,61 +504,12 @@ _gdk_wayland_device_get_keymap (GdkDevice *device) return GDK_WAYLAND_DEVICE (device)->device->keymap; } -struct _DataOffer { - struct wl_data_offer *offer; - gint ref_count; - GPtrArray *types; -}; - -static void -data_offer_offer (void *data, - struct wl_data_offer *wl_data_offer, - const char *type) -{ - DataOffer *offer = (DataOffer *)data; - g_debug (G_STRLOC ": %s wl_data_offer = %p type = %s", - G_STRFUNC, wl_data_offer, type); - - g_ptr_array_add (offer->types, g_strdup (type)); -} - -static void -data_offer_unref (DataOffer *offer) -{ - offer->ref_count--; - - if (offer->ref_count == 0) - { - g_ptr_array_free (offer->types, TRUE); - g_free (offer); - } -} - -static const struct wl_data_offer_listener data_offer_listener = { - data_offer_offer, -}; - static void data_device_data_offer (void *data, struct wl_data_device *data_device, struct wl_data_offer *_offer) { - DataOffer *offer; - - /* This structure is reference counted to handle the case where you get a - * leave but are in the middle of transferring data - */ - offer = g_new0 (DataOffer, 1); - offer->ref_count = 1; - offer->types = g_ptr_array_new_with_free_func (g_free); - offer->offer = _offer; - - /* The DataOffer structure is then retrieved later since this sets the user - * data. - */ - wl_data_offer_add_listener (offer->offer, - &data_offer_listener, - offer); + gdk_wayland_selection_set_offer (_offer); } static void @@ -583,11 +526,6 @@ data_device_enter (void *data, g_debug (G_STRLOC ": %s data_device = %p serial = %u, surface = %p, x = %d y = %d, offer = %p", G_STRFUNC, data_device, serial, surface, x, y, offer); - /* Retrieve the DataOffer associated with with the wl_data_offer - this - * association is made when the listener is attached. - */ - g_assert (device->drag_offer == NULL); - device->drag_offer = wl_data_offer_get_user_data (offer); } static void @@ -599,8 +537,6 @@ data_device_leave (void *data, g_debug (G_STRLOC ": %s data_device = %p", G_STRFUNC, data_device); - data_offer_unref (device->drag_offer); - device->drag_offer = NULL; } static void @@ -627,33 +563,10 @@ data_device_selection (void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *offer) { - GdkWaylandDeviceData *device = (GdkWaylandDeviceData *)data; - g_debug (G_STRLOC ": %s wl_data_device = %p wl_data_offer = %p", G_STRFUNC, wl_data_device, offer); - if (!offer) - { - if (device->selection_offer) - { - data_offer_unref (device->selection_offer); - device->selection_offer = NULL; - } - - return; - } - - if (device->selection_offer) - { - data_offer_unref (device->selection_offer); - device->selection_offer = NULL; - } - - /* Retrieve the DataOffer associated with with the wl_data_offer - - * this association is made when the listener is attached. - */ - g_assert (device->selection_offer == NULL); - device->selection_offer = wl_data_offer_get_user_data (offer); + gdk_wayland_selection_set_offer (offer); } static const struct wl_data_device_listener data_device_listener = { @@ -1876,290 +1789,6 @@ _gdk_wayland_device_get_last_implicit_grab_serial (GdkWaylandDevice *device, return serial; } -static GdkAtom -mime_type_to_gdk_atom (char *mime_type) -{ - if (strcmp (mime_type, "text/plain;charset=utf8")) - return gdk_atom_intern_static_string ("UTF8_STRING"); - - return GDK_NONE; -} - -gint -gdk_wayland_device_get_selection_type_atoms (GdkDevice *gdk_device, - GdkAtom **atoms_out) -{ - gint i; - GdkAtom *atoms; - GdkWaylandDeviceData *device; - - g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), 0); - g_return_val_if_fail (atoms_out != NULL, 0); - - device = GDK_WAYLAND_DEVICE (gdk_device)->device; - - if (!device->selection_offer || device->selection_offer->types->len == 0) - { - *atoms_out = NULL; - return 0; - } - - atoms = g_new0 (GdkAtom, device->selection_offer->types->len); - - /* Convert list of targets to atoms */ - for (i = 0; i < device->selection_offer->types->len; i++) - atoms[i] = mime_type_to_gdk_atom (device->selection_offer->types->pdata[i]); - - *atoms_out = atoms; - return device->selection_offer->types->len; -} - -typedef struct -{ - GdkWaylandDeviceData *device; - DataOffer *offer; - GIOChannel *channel; - GdkDeviceWaylandRequestContentCallback cb; - gpointer userdata; -} RequestContentClosure; - -static gboolean -_request_content_io_func (GIOChannel *channel, - GIOCondition condition, - gpointer userdata) -{ - RequestContentClosure *closure = (RequestContentClosure *)userdata; - gchar *data = NULL; - gsize len = 0; - GError *error = NULL; - - /* FIXME: We probably want to do something better than this - * to avoid blocking on the transfer of large pieces of data: - * call the callback multiple times I should think. - */ - if (g_io_channel_read_to_end (channel, &data, &len, &error) != G_IO_STATUS_NORMAL) - { - g_warning (G_STRLOC ": Error reading content from pipe: %s", error->message); - g_clear_error (&error); - } - - /* Since we use _read_to_end we've got a guaranteed EOF and thus can go - * ahead and close the fd - */ - g_io_channel_shutdown (channel, TRUE, NULL); - - closure->cb (closure->device->pointer, data, len, closure->userdata); - - g_free (data); - data_offer_unref (closure->offer); - g_io_channel_unref (channel); - g_free (closure); - - return FALSE; -} - -gboolean -gdk_wayland_device_request_selection_content (GdkDevice *gdk_device, - const gchar *requested_mime_type, - GdkDeviceWaylandRequestContentCallback cb, - gpointer userdata) -{ - int pipe_fd[2]; - RequestContentClosure *closure; - GdkWaylandDeviceData *device; - GError *error = NULL; - - g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), FALSE); - g_return_val_if_fail (requested_mime_type != NULL, FALSE); - g_return_val_if_fail (cb != NULL, FALSE); - - device = GDK_WAYLAND_DEVICE (gdk_device)->device; - - if (!device->selection_offer) - return FALSE; - - /* TODO: Check mimetypes */ - - closure = g_new0 (RequestContentClosure, 1); - - device->selection_offer->ref_count++; - - pipe2 (pipe_fd, O_CLOEXEC); - wl_data_offer_receive (device->selection_offer->offer, - requested_mime_type, - pipe_fd[1]); - close (pipe_fd[1]); - - closure->device = device; - closure->offer = device->selection_offer; - closure->channel = g_io_channel_unix_new (pipe_fd[0]); - closure->cb = cb; - closure->userdata = userdata; - - if (!g_io_channel_set_encoding (closure->channel, NULL, &error)) - { - g_warning (G_STRLOC ": Error setting encoding on channel: %s", - error->message); - g_clear_error (&error); - goto error; - } - - g_io_add_watch (closure->channel, - G_IO_IN, - _request_content_io_func, - closure); - - return TRUE; - - error: - data_offer_unref (closure->offer); - g_io_channel_unref (closure->channel); - close (pipe_fd[1]); - g_free (closure); - - return FALSE; -} - -struct _GdkWaylandSelectionOffer { - GdkDeviceWaylandOfferContentCallback cb; - gpointer userdata; - struct wl_data_source *source; - GdkWaylandDeviceData *device; -}; - -static void -data_source_target (void *data, - struct wl_data_source *source, - const char *mime_type) -{ - g_debug (G_STRLOC ": %s source = %p, mime_type = %s", - G_STRFUNC, source, mime_type); -} - -static void -data_source_send (void *data, - struct wl_data_source *source, - const char *mime_type, - int32_t fd) -{ - GdkWaylandSelectionOffer *offer = (GdkWaylandSelectionOffer *)data; - gchar *buf; - gssize len, bytes_written = 0; - - g_debug (G_STRLOC ": %s source = %p, mime_type = %s fd = %d", - G_STRFUNC, source, mime_type, fd); - - buf = offer->cb (offer->device->pointer, mime_type, &len, offer->userdata); - - while (len > 0) - { - bytes_written += write (fd, buf + bytes_written, len); - if (bytes_written == -1) - goto error; - len -= bytes_written; - } - - close (fd); - g_free (buf); - - return; - error: - - g_warning (G_STRLOC ": Error writing data to client: %s", - g_strerror (errno)); - - close (fd); - g_free (buf); -} - -static void -data_source_cancelled (void *data, - struct wl_data_source *source) -{ - g_debug (G_STRLOC ": %s source = %p", - G_STRFUNC, source); -} - -static const struct wl_data_source_listener data_source_listener = { - data_source_target, - data_source_send, - data_source_cancelled -}; - -static guint32 -_wl_time_now (void) -{ - struct timeval tv; - - gettimeofday (&tv, NULL); - - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -gboolean -gdk_wayland_device_offer_selection_content (GdkDevice *gdk_device, - const gchar **mime_types, - gint nr_mime_types, - GdkDeviceWaylandOfferContentCallback cb, - gpointer userdata) -{ - GdkDisplay *display; - GdkWaylandDisplay *display_wayland; - GdkWaylandSelectionOffer *offer; - GdkWaylandDeviceData *device; - gint i; - - g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), 0); - device = GDK_WAYLAND_DEVICE (gdk_device)->device; - - display = device->display; - display_wayland = GDK_WAYLAND_DISPLAY (display); - - offer = g_new0 (GdkWaylandSelectionOffer, 1); - offer->cb = cb; - offer->userdata = userdata; - offer->source = - wl_data_device_manager_create_data_source (display_wayland->data_device_manager); - offer->device = device; - - for (i = 0; i < nr_mime_types; i++) - wl_data_source_offer (offer->source, mime_types[i]); - - wl_data_source_add_listener (offer->source, - &data_source_listener, - offer); - - wl_data_device_set_selection (device->data_device, - offer->source, - _gdk_wayland_display_get_serial (display_wayland)); - - device->selection_offer_out = offer; - - return TRUE; -} - -gboolean -gdk_wayland_device_clear_selection_content (GdkDevice *gdk_device) -{ - GdkWaylandDeviceData *device; - - g_return_val_if_fail (GDK_IS_WAYLAND_DEVICE (gdk_device), 0); - device = GDK_WAYLAND_DEVICE (gdk_device)->device; - - if (!device->selection_offer_out) - return FALSE; - - wl_data_device_set_selection (device->data_device, - NULL, - _wl_time_now ()); - - wl_data_source_destroy (device->selection_offer_out->source); - g_free (device->selection_offer_out); - device->selection_offer_out = NULL; - - return TRUE; -} - void gdk_wayland_device_unset_touch_grab (GdkDevice *gdk_device, GdkEventSequence *sequence) diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c index 1a75dd03c0..37c197da5f 100644 --- a/gdk/wayland/gdkselection-wayland.c +++ b/gdk/wayland/gdkselection-wayland.c @@ -886,3 +886,41 @@ _gdk_wayland_display_utf8_to_string_target (GdkDisplay *display, { return NULL; } + +void +gdk_wayland_selection_add_targets (GdkWindow *window, + GdkAtom selection, + guint ntargets, + GdkAtom *targets) +{ + struct wl_data_source *data_source; + guint i; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + data_source = gdk_wayland_selection_get_data_source (window, selection); + + if (!data_source) + return; + + for (i = 0; i < ntargets; i++) + wl_data_source_offer (data_source, gdk_atom_name (targets[i])); + + if (selection == atoms[ATOM_CLIPBOARD]) + { + GdkDeviceManager *device_manager; + GdkDisplay *display; + GdkDevice *device; + + display = gdk_display_get_default (); + device_manager = gdk_display_get_device_manager (display); + device = gdk_device_manager_get_client_pointer (device_manager); + gdk_wayland_device_set_selection (device, data_source); + } +} + +void +gdk_wayland_selection_clear_targets (GdkAtom selection) +{ + gdk_wayland_selection_unset_data_source (selection); +} diff --git a/gdk/wayland/gdkwaylandselection.h b/gdk/wayland/gdkwaylandselection.h index 7c5d5d2a27..90474c0305 100644 --- a/gdk/wayland/gdkwaylandselection.h +++ b/gdk/wayland/gdkwaylandselection.h @@ -34,37 +34,19 @@ G_BEGIN_DECLS #if defined (GTK_COMPILATION) || defined (GDK_COMPILATION) -#define gdk_wayland_device_get_selection_type_atoms gdk_wayland_device_get_selection_type_atoms_libgtk_only +#define gdk_wayland_selection_add_targets gdk_wayland_selection_add_targets_libgtk_only GDK_AVAILABLE_IN_ALL -int -gdk_wayland_device_get_selection_type_atoms (GdkDevice *device, - GdkAtom **atoms_out); +void +gdk_wayland_selection_add_targets (GdkWindow *window, + GdkAtom selection, + guint ntargets, + GdkAtom *targets); -typedef void (*GdkDeviceWaylandRequestContentCallback) (GdkDevice *device, const gchar *data, gsize len, gpointer userdata); - -#define gdk_wayland_device_request_selection_content gdk_wayland_device_request_selection_content_libgtk_only +#define gdk_wayland_selection_clear_targets gdk_wayland_selection_clear_targets_libgtk_only GDK_AVAILABLE_IN_ALL -gboolean -gdk_wayland_device_request_selection_content (GdkDevice *device, - const gchar *requested_mime_type, - GdkDeviceWaylandRequestContentCallback cb, - gpointer userdata); - -typedef gchar *(*GdkDeviceWaylandOfferContentCallback) (GdkDevice *device, const gchar *mime_type, gssize *len, gpointer userdata); +void +gdk_wayland_selection_clear_targets (GdkAtom selection); -#define gdk_wayland_device_offer_selection_content gdk_wayland_device_offer_selection_content_libgtk_only -GDK_AVAILABLE_IN_ALL -gboolean -gdk_wayland_device_offer_selection_content (GdkDevice *gdk_device, - const gchar **mime_types, - gint nr_mime_types, - GdkDeviceWaylandOfferContentCallback cb, - gpointer userdata); - -#define gdk_wayland_device_clear_selection_content gdk_wayland_device_clear_selection_content_libgtk_only -GDK_AVAILABLE_IN_ALL -gboolean -gdk_wayland_device_clear_selection_content (GdkDevice *gdk_device); #endif diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 349b712547..2ec3cd2957 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -526,7 +526,6 @@ gtk_private_h_sources = \ gtkcairoblurprivate.h \ gtkcellareaboxcontextprivate.h \ gtkclipboardprivate.h \ - gtkclipboard-waylandprivate.h \ gtkcolorswatchprivate.h \ gtkcoloreditorprivate.h \ gtkcolorplaneprivate.h \ @@ -1237,7 +1236,6 @@ else # No wayland gtkdnd-wayland.c yet gtk_clipboard_dnd_c_sources = \ gtkclipboard.c \ - gtkclipboard-wayland.c \ gtkdnd.c endif diff --git a/gtk/gtkclipboard-wayland.c b/gtk/gtkclipboard-wayland.c deleted file mode 100644 index ccd3cf7da4..0000000000 --- a/gtk/gtkclipboard-wayland.c +++ /dev/null @@ -1,365 +0,0 @@ -/* GTK - The GIMP Toolkit - * Copyright (C) 2000 Red Hat, Inc. - * Copyright (C) 2004 Nokia Corporation - * Copyright (C) 2006-2008 Imendio AB - * Copyright (C) 2011-2012 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - * - */ - -#include "config.h" - -#include "gtkclipboard-waylandprivate.h" - -#ifdef GDK_WINDOWING_WAYLAND - -#include - -#include "gtkmain.h" -#include "gtkmarshalers.h" -#include "gtkintl.h" -#include "gtkselectionprivate.h" - -static void gtk_clipboard_wayland_owner_change (GtkClipboard *clipboard, - GdkEventOwnerChange *event); -static gboolean gtk_clipboard_wayland_set_contents (GtkClipboard *clipboard, - const GtkTargetEntry *targets, - guint n_targets, - GtkClipboardGetFunc get_func, - GtkClipboardClearFunc clear_func, - gpointer user_data, - gboolean have_owner); -static void gtk_clipboard_wayland_clear (GtkClipboard *clipboard); -static void gtk_clipboard_wayland_request_contents (GtkClipboard *clipboard, - GdkAtom target, - GtkClipboardReceivedFunc callback, - gpointer user_data); -static void gtk_clipboard_wayland_set_can_store (GtkClipboard *clipboard, - const GtkTargetEntry *targets, - gint n_targets); -static void gtk_clipboard_wayland_store (GtkClipboard *clipboard); - -G_DEFINE_TYPE (GtkClipboardWayland, gtk_clipboard_wayland, GTK_TYPE_CLIPBOARD); - -static void -gtk_clipboard_wayland_class_init (GtkClipboardWaylandClass *klass) -{ - GtkClipboardClass *clipboard_class = GTK_CLIPBOARD_CLASS (klass); - - clipboard_class->set_contents = gtk_clipboard_wayland_set_contents; - clipboard_class->clear = gtk_clipboard_wayland_clear; - clipboard_class->request_contents = gtk_clipboard_wayland_request_contents; - clipboard_class->set_can_store = gtk_clipboard_wayland_set_can_store; - clipboard_class->store = gtk_clipboard_wayland_store; - clipboard_class->owner_change = gtk_clipboard_wayland_owner_change; -} - -static void -gtk_clipboard_wayland_init (GtkClipboardWayland *clipboard) -{ -} - -struct _SetContentClosure { - GtkClipboard *clipboard; - GtkClipboardGetFunc get_func; - GtkClipboardClearFunc clear_func; - guint info; - gboolean have_owner; - gpointer userdata; - GtkTargetPair *targets; - gint n_targets; -}; - -static gchar * -_offer_cb (GdkDevice *device, - const gchar *mime_type, - gssize *len, - gpointer userdata) -{ - SetContentClosure *closure = (SetContentClosure *)userdata; - GtkSelectionData selection_data = { 0, }; - guint info = 0; - gint i; - - selection_data.target = gdk_atom_intern (mime_type, FALSE); - - for (i = 0; i < closure->n_targets; i++) - { - if (closure->targets[i].target == selection_data.target) - { - info = closure->targets[i].info; - break; - } - } - - closure->get_func (closure->clipboard, - &selection_data, - info, - closure->userdata); - - *len = gtk_selection_data_get_length (&selection_data); - - /* The caller of this callback will free this data - the GtkClipboardGetFunc - * uses gtk_selection_data_set which copies*/ - return (gchar *)selection_data.data; -} - -static void -clipboard_owner_destroyed (gpointer data, - GObject *owner) -{ - GtkClipboardWayland *clipboard = GTK_CLIPBOARD_WAYLAND (data); - GtkClipboard *gtkclipboard = GTK_CLIPBOARD (data); - SetContentClosure *last_closure = clipboard->last_closure; - - last_closure->userdata = NULL; - last_closure->get_func = NULL; - last_closure->clear_func = NULL; - last_closure->have_owner = FALSE; - - gtk_clipboard_clear (gtkclipboard); -} - -static gboolean -gtk_clipboard_wayland_set_contents (GtkClipboard *gtkclipboard, - const GtkTargetEntry *targets, - guint n_targets, - GtkClipboardGetFunc get_func, - GtkClipboardClearFunc clear_func, - gpointer user_data, - gboolean have_owner) -{ - GtkClipboardWayland *clipboard = GTK_CLIPBOARD_WAYLAND (gtkclipboard); - GdkDeviceManager *device_manager; - GdkDevice *device; - gint i, j; - gchar **mimetypes; - SetContentClosure *closure, *last_closure; - - if (gtkclipboard->selection != GDK_SELECTION_CLIPBOARD) - return FALSE; - - last_closure = clipboard->last_closure; - if (!last_closure || - (!last_closure->have_owner && have_owner) || - (last_closure->userdata != user_data)) { - gtk_clipboard_clear (gtkclipboard); - - closure = g_new0 (SetContentClosure, 1); - closure->clipboard = gtkclipboard; - closure->userdata = user_data; - closure->have_owner = have_owner; - - if (have_owner) - g_object_weak_ref (G_OBJECT (user_data), clipboard_owner_destroyed, clipboard); - } else { - closure = last_closure; - g_free (closure->targets); - } - - closure->get_func = get_func; - closure->clear_func = clear_func; - closure->targets = g_new0 (GtkTargetPair, n_targets); - - device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); - device = gdk_device_manager_get_client_pointer (device_manager); - - mimetypes = g_new (gchar *, n_targets); - - for (i = 0, j = 0; i < n_targets; i++) - { - if (strcmp(targets[i].target, "COMPOUND_TEXT") == 0) - continue; - if (strcmp(targets[i].target, "UTF8_STRING") == 0) - continue; - if (strcmp(targets[i].target, "TEXT") == 0) - continue; - if (strcmp(targets[i].target, "STRING") == 0) - continue; - if (strcmp(targets[i].target, "GTK_TEXT_BUFFER_CONTENTS") == 0) - continue; - - mimetypes[j] = targets[i].target; - closure->targets[j].target = gdk_atom_intern (targets[i].target, FALSE); - closure->targets[j].flags = targets[i].flags; - closure->targets[j].info = targets[i].info; - j++; - } - - closure->n_targets = j; - - gdk_wayland_device_offer_selection_content (device, - (const gchar **)mimetypes, - j, - _offer_cb, - closure); - clipboard->last_closure = closure; - - g_free (mimetypes); - return TRUE; -} - -static void -gtk_clipboard_wayland_clear (GtkClipboard *gtkclipboard) -{ - GtkClipboardWayland *clipboard = GTK_CLIPBOARD_WAYLAND (gtkclipboard); - GdkDeviceManager *device_manager; - GdkDevice *device; - - if (!clipboard->last_closure) - return; - - device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); - device = gdk_device_manager_get_client_pointer (device_manager); - - gdk_wayland_device_clear_selection_content (device); - - if (clipboard->last_closure->clear_func) - { - clipboard->last_closure->clear_func (gtkclipboard, - clipboard->last_closure->userdata); - } - - if (clipboard->last_closure->have_owner) - g_object_weak_unref (G_OBJECT (clipboard->last_closure->userdata), - clipboard_owner_destroyed, clipboard); - g_free (clipboard->last_closure->targets); - g_free (clipboard->last_closure); - - clipboard->last_closure = NULL; -} - -typedef struct { - GtkClipboard *clipboard; - GCallback cb; - gpointer userdata; - GdkAtom target; -} ClipboardRequestClosure; - -static void -_request_generic_cb (GdkDevice *device, - const gchar *data, - gsize len, - gpointer userdata) -{ - ClipboardRequestClosure *closure = (ClipboardRequestClosure *)userdata; - GtkClipboardReceivedFunc cb = (GtkClipboardReceivedFunc)closure->cb; - GtkSelectionData selection_data; - - selection_data.selection = GDK_SELECTION_CLIPBOARD; - selection_data.target = closure->target; - selection_data.type = closure->target; - selection_data.length = len; - selection_data.data = (guchar *)data; - - cb (closure->clipboard, &selection_data, closure->userdata); - - g_free (closure); -} - -static void -gtk_clipboard_wayland_request_contents (GtkClipboard *gtkclipboard, - GdkAtom target, - GtkClipboardReceivedFunc callback, - gpointer user_data) -{ - GdkDeviceManager *device_manager; - GdkDevice *device; - ClipboardRequestClosure *closure; - gchar *mime_type; - - device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); - device = gdk_device_manager_get_client_pointer (device_manager); - - if (target == gdk_atom_intern_static_string ("TARGETS")) - { - GtkSelectionData selection_data; - int n_atoms; - GdkAtom *atoms; - - selection_data.selection = GDK_NONE; - selection_data.format = 32; - selection_data.type = GDK_SELECTION_TYPE_ATOM; - - n_atoms = gdk_wayland_device_get_selection_type_atoms (device, &atoms); - selection_data.length = n_atoms; - selection_data.data = (guchar *) atoms; - - callback (gtkclipboard, &selection_data, user_data); - return; - } - - /* When GTK+ requests text, it tries UTF8_STRING first and then - * falls back to COMPOUND_TEXT and then STRING. We rewrite - * UTF8_STRING to text/plain;charset=utf-8, and if that doesn't - * work, just fail the fallback targets. Maybe we could do this in - * a generic way that just compares the target against the targets - * advertised by the data offer. */ - if (target == gdk_atom_intern_static_string ("UTF8_STRING")) - target = gdk_atom_intern_static_string ("text/plain;charset=utf-8"); - else if (target == gdk_atom_intern_static_string ("COMPOUND_TEXT") || - target == GDK_TARGET_STRING) - { - GtkSelectionData selection_data; - - selection_data.selection = GDK_NONE; - selection_data.target = GDK_NONE; - selection_data.type = GDK_NONE; - selection_data.length = 0; - selection_data.data = NULL; - - callback (gtkclipboard, &selection_data, user_data); - return; - } - - closure = g_new0 (ClipboardRequestClosure, 1); - closure->clipboard = gtkclipboard; - closure->cb = (GCallback)callback; - closure->userdata = user_data; - closure->target = target; - - /* TODO: Do we need to check that target is valid ? */ - mime_type = gdk_atom_name (target); - - gdk_wayland_device_request_selection_content (device, - mime_type, - _request_generic_cb, - closure); - - g_free (mime_type); -} - -static void -gtk_clipboard_wayland_owner_change (GtkClipboard *clipboard, - GdkEventOwnerChange *event) -{ - -} - -static void -gtk_clipboard_wayland_set_can_store (GtkClipboard *clipboard, - const GtkTargetEntry *targets, - gint n_targets) -{ - /* FIXME: Implement */ -} - -static void -gtk_clipboard_wayland_store (GtkClipboard *clipboard) -{ - /* FIXME: Implement */ -} - -#endif /* GDK_WINDOWING_WAYLAND */ diff --git a/gtk/gtkclipboard-waylandprivate.h b/gtk/gtkclipboard-waylandprivate.h deleted file mode 100644 index 466d63ef68..0000000000 --- a/gtk/gtkclipboard-waylandprivate.h +++ /dev/null @@ -1,60 +0,0 @@ -/* GTK - The GIMP Toolkit - * Copyright (C) 2000 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - */ - -#ifndef __GTK_CLIPBOARD_WAYLAND_WAYLAND_PRIVATE_H__ -#define __GTK_CLIPBOARD_WAYLAND_WAYLAND_PRIVATE_H__ - -#include - -#ifdef GDK_WINDOWING_WAYLAND - -#include -#include - -G_BEGIN_DECLS - -#define GTK_TYPE_CLIPBOARD_WAYLAND (gtk_clipboard_wayland_get_type ()) -#define GTK_CLIPBOARD_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CLIPBOARD_WAYLAND, GtkClipboardWayland)) -#define GTK_IS_CLIPBOARD_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CLIPBOARD_WAYLAND)) -#define GTK_CLIPBOARD_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CLIPBOARD_WAYLAND, GtkClipboardWaylandClass)) -#define GTK_IS_CLIPBOARD_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CLIPBOARD_WAYLAND)) -#define GTK_CLIPBOARD_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CLIPBOARD_WAYLAND, GtkClipboardWaylandClass)) - -typedef struct _GtkClipboardWayland GtkClipboardWayland; -typedef struct _GtkClipboardWaylandClass GtkClipboardWaylandClass; - -typedef struct _SetContentClosure SetContentClosure; - -struct _GtkClipboardWayland -{ - GtkClipboard parent_instance; - - SetContentClosure *last_closure; -}; - -struct _GtkClipboardWaylandClass -{ - GtkClipboardClass parent_class; -}; - -GType gtk_clipboard_wayland_get_type (void) G_GNUC_CONST; - -G_END_DECLS - -#endif /* GDK_WINDOWING_WAYLAND */ - -#endif /* __GTK_CLIPBOARD_WAYLAND_WAYLAND_PRIVATE_H__ */ diff --git a/gtk/gtkclipboard.c b/gtk/gtkclipboard.c index 682634695e..302f7f73f1 100644 --- a/gtk/gtkclipboard.c +++ b/gtk/gtkclipboard.c @@ -23,9 +23,6 @@ #include "gtkclipboard.h" #include "gtkclipboardprivate.h" -#ifdef GDK_WINDOWING_WAYLAND -#include "gtkclipboard-waylandprivate.h" -#endif #include "gtkinvisible.h" #include "gtkmain.h" #include "gtkmarshalers.h" @@ -1917,12 +1914,7 @@ clipboard_peek (GdkDisplay *display, if (!tmp_list && !only_if_exists) { -#ifdef GDK_WINDOWING_WAYLAND - if (GDK_IS_WAYLAND_DISPLAY (display)) - clipboard = g_object_new (GTK_TYPE_CLIPBOARD_WAYLAND, NULL); - else -#endif - clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL); + clipboard = g_object_new (GTK_TYPE_CLIPBOARD, NULL); clipboard->selection = selection; clipboard->display = display; diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c index bd9d22b0d5..2adba2e892 100644 --- a/gtk/gtkselection.c +++ b/gtk/gtkselection.c @@ -98,6 +98,10 @@ #include "win32/gdkwin32.h" #endif +#ifdef GDK_WINDOWING_WAYLAND +#include +#endif + #undef DEBUG_SELECTION /* Maximum size of a sent chunk, in bytes. Also the default size of @@ -879,6 +883,11 @@ gtk_selection_clear_targets (GtkWidget *widget, g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (selection != GDK_NONE); +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget))) + gdk_wayland_selection_clear_targets (selection); +#endif + lists = g_object_get_data (G_OBJECT (widget), gtk_selection_handler_key); tmp_list = lists; @@ -923,6 +932,10 @@ gtk_selection_add_target (GtkWidget *widget, list = gtk_selection_target_list_get (widget, selection); gtk_target_list_add (list, target, 0, info); +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget))) + gdk_wayland_selection_add_targets (gtk_widget_get_window (widget), selection, 1, &target); +#endif #ifdef GDK_WINDOWING_WIN32 gdk_win32_selection_add_targets (gtk_widget_get_window (widget), selection, 1, &target); #endif @@ -953,6 +966,20 @@ gtk_selection_add_targets (GtkWidget *widget, list = gtk_selection_target_list_get (widget, selection); gtk_target_list_add_table (list, targets, ntargets); +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget))) + { + GdkAtom *atoms = g_new (GdkAtom, ntargets); + guint i; + + for (i = 0; i < ntargets; i++) + atoms[i] = gdk_atom_intern (targets[i].target, FALSE); + + gdk_wayland_selection_add_targets (gtk_widget_get_window (widget), selection, ntargets, atoms); + g_free (atoms); + } +#endif + #ifdef GDK_WINDOWING_WIN32 { int i; -- 2.30.2